package com.origin.onlinesys.web.filters;

import org.apache.shiro.authc.AccountException;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;

import javax.security.auth.login.LoginException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.swing.plaf.SeparatorUI;

/**
 * Created by Administrator on 2015/1/7.
 * 验证码过滤器
 */
public class CaptchaAuthenticationFilter extends FormAuthenticationFilter {

    //验证码默认参数名称
    public static final String DEFAULT_CAPTCH_PARAME = "captcha";
    //是否显示验证码key
    public static final String DEFAULT_CAPTCH_ISSHOW = "show_captcha";
    //默认存储登录错误次数
    public static final String DEFAULT_LOGERROR_NUM  = "logerror_num";

    //验证码参数名称
    private String captchaParame  = DEFAULT_CAPTCH_PARAME;

    //保存验证码key
    private String saveCaptchaKey = DEFAULT_CAPTCH_PARAME;

    //登录错误次数key
    private String logErrorNumKey = DEFAULT_LOGERROR_NUM;

    //是否显示验证码key
    private String logShowCaptchaKey = DEFAULT_CAPTCH_ISSHOW;

    //登录最大错误次数
    private int maxErrorNum = 3;


    /**
     * 执行登录操作
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
        Session session = getSubject(request,response).getSession();
        //获取登录错误的次数
        Integer num = (Integer)session.getAttribute(getLogErrorNumKey());
        if(num == null){
            num  = new Integer(1);
            session.setAttribute(getLogErrorNumKey(),num);
        }

        //获取当前保存的验证码
        String curretnCaptcha = (String)session.getAttribute(getSaveCaptchaKey());
        //获取提交的验证码
        String submitCaptcha  = getCaptcha(request);
        //判断验证码是否一致
        if(curretnCaptcha != null  && !curretnCaptcha.equalsIgnoreCase(submitCaptcha)){
            return  onLoginFailure(createToken(request,response),new AccountException("验证码错误"),request,response);
        }
        return super.executeLogin(request, response);
    }


    /**
     * 设置错误提示
     * @param request
     * @param ae
     */
    @Override
    protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
        request.setAttribute(getFailureKeyAttribute(),ae.getMessage());
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        Session session = getSubject(request, response).getSession(false);
        Integer number = (Integer) session
                .getAttribute(getLogErrorNumKey());

        //登录错误大于最大错误次数
        if(number > getMaxErrorNum()){
            //显示验证码
            session.setAttribute(getLogShowCaptchaKey(),true);
        }
        //计数+1
        session.setAttribute(getLogErrorNumKey(),++number);

        //设置错误信息
        setFailureAttribute(request,e);

        return true;
    }

    /**
     * 登录成功执行
     * @param token
     * @param subject
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {

        Session session = subject.getSession(false);

        //清除登录保存的数据
        session.removeAttribute(getLogErrorNumKey());
        session.removeAttribute(getLogShowCaptchaKey());
        session.removeAttribute(getSaveCaptchaKey());

        //获取数据
        subject.getPrincipal();


        return super.onLoginSuccess(token, subject, request, response);
    }


    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) {


        return super.createToken(request, response);
    }

    /**
     * 获取验证码
     * @param request
     * @return
     */
    public String getCaptcha(ServletRequest  request){
        return  WebUtils.getCleanParam(request,getCaptchaParame());
    }

    public int getMaxErrorNum() {
        return maxErrorNum;
    }

    public void setMaxErrorNum(int maxErrorNum) {
        this.maxErrorNum = maxErrorNum;
    }

    public String getCaptchaParame() {
        return captchaParame;
    }

    public void setCaptchaParame(String captchaParame) {
        this.captchaParame = captchaParame;
    }

    public String getSaveCaptchaKey() {
        return saveCaptchaKey;
    }

    public void setSaveCaptchaKey(String saveCaptchaKey) {
        this.saveCaptchaKey = saveCaptchaKey;
    }

    public String getLogErrorNumKey() {
        return logErrorNumKey;
    }

    public void setLogErrorNumKey(String logErrorNumKey) {
        this.logErrorNumKey = logErrorNumKey;
    }

    public String getLogShowCaptchaKey() {
        return logShowCaptchaKey;
    }

    public void setLogShowCaptchaKey(String logShowCaptchaKey) {
        this.logShowCaptchaKey = logShowCaptchaKey;
    }
}
